package cn.fintecher.pangolin.service.business.service;

import cn.fintecher.pangolin.common.enums.*;
import cn.fintecher.pangolin.common.model.DepartmentModel;
import cn.fintecher.pangolin.common.model.UserModel;
import cn.fintecher.pangolin.entity.mysql.AssistCase;
import cn.fintecher.pangolin.entity.mysql.CaseInfo;
import cn.fintecher.pangolin.entity.mysql.QAssistCase;
import cn.fintecher.pangolin.entity.mysql.QCaseInfo;
import cn.fintecher.pangolin.service.business.model.response.AppHomeResponse;
import cn.fintecher.pangolin.service.business.repository.jparepository.AssistCaseRepository;
import cn.fintecher.pangolin.service.business.repository.jparepository.CaseInfoRepository;
import cn.fintecher.pangolin.service.business.task.AppHomeTask;
import org.apache.commons.collections4.IterableUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.stream.Collectors;

/**
 * @Auther: xiaqun
 * @Description:
 * @Date: 16:58 2019/11/13
 */

@Service("appHomeService")
public class AppHomeService {
    private static final Logger log = LoggerFactory.getLogger(AppHomeService.class);

    @Autowired
    private BaseService baseService;

    @Autowired
    private AssistCaseRepository assistCaseRepository;

    @Autowired
    private CaseInfoRepository caseInfoRepository;

    @Autowired
    private AppHomeTask appHomeTask;

    /**
     * 首页相关统计
     */
    public AppHomeResponse getHomePage(String token) {
        UserModel userModel = baseService.getUserByToken(token);
        Iterable<AssistCase> iterable;
        QAssistCase qAssistCase = QAssistCase.assistCase;
        if (userModel.getIsManage().equals(BaseSelect.YES)) {
            DepartmentModel departmentModel = baseService.getDepartmentByToken(token);
            iterable = assistCaseRepository.findAll(qAssistCase.assistCollector.department.departCode.like(departmentModel.getDepartCode() + "%").and(qAssistCase.assistStatus.eq(AssistStatus.ASSIST_COLLECTING)));
        } else {
            iterable = assistCaseRepository.findAll(qAssistCase.assistCollector.id.eq(userModel.getId()).and(qAssistCase.assistStatus.eq(AssistStatus.ASSIST_COLLECTING)));
        }
        List<AssistCase> list = IterableUtils.toList(iterable);
        AppHomeResponse response = new AppHomeResponse();
        if (!list.isEmpty()) {
            List<CompletableFuture<AppHomeResponse>> futures = new ArrayList<>();
            int pageSize = 2000;
            int pageNumber = (int) Math.ceil((double) list.size() / (double) pageSize);
            for (int i = 0; i < pageNumber; i++) {
                List<AssistCase> assistCases = list.stream().skip(i * pageSize).limit(pageSize).collect(Collectors.toList());
                CompletableFuture<AppHomeResponse> task = appHomeTask.getHome(assistCases, userModel.getId());
                futures.add(task);
            }
            List<AppHomeResponse> responses = new ArrayList<>();
            try {
                for (CompletableFuture<AppHomeResponse> future : futures) {
                    responses.add(future.get());
                }
            } catch (InterruptedException | ExecutionException e) {
                log.error(e.getMessage(), e);
            }
            Double waitCollAmt = 0d;
            Double hadPayAmt = 0d;
            Integer waitVisitNum = 0;
            Integer hasVisitNum = 0;
            Integer expireNum = 0;
            Integer nearThreeDays = 0;
            for (AppHomeResponse appHomeResponse : responses) {
                waitCollAmt += appHomeResponse.getWaitCollAmt();
                hadPayAmt += appHomeResponse.getHadPayAmt();
                waitVisitNum += appHomeResponse.getWaitVisitNum();
                hasVisitNum += appHomeResponse.getHasVisitNum();
                expireNum += appHomeResponse.getExpireNum();
                nearThreeDays += appHomeResponse.getNearThreeDays();
            }
            response.setVisitNum(list.size());
            response.setWaitCollAmt(waitCollAmt);
            response.setHadPayAmt(hadPayAmt);
            response.setWaitVisitNum(waitVisitNum);
            response.setHasVisitNum(hasVisitNum);
            response.setExpireNum(expireNum);
            response.setNearThreeDays(nearThreeDays);
        }
        Iterable<CaseInfo> caseInfoIterable;
        QCaseInfo qCaseInfo = QCaseInfo.caseInfo;
        if (userModel.getIsManage().equals(BaseSelect.YES)) {
            DepartmentModel departmentModel = baseService.getDepartmentByToken(token);
            caseInfoIterable = caseInfoRepository.findAll(qCaseInfo.currentCollector.department.departCode.like(departmentModel.getDepartCode() + "%").and(qCaseInfo.caseType.eq(CaseType.VISIT_CASE)
                    .and(qCaseInfo.caseDataStatus.eq(CaseDataStatus.IN_POOL))).and(qCaseInfo.publicCaseFlag.eq(PublicCaseFlag.NO_PUBLIC_CASE)));
        } else {
            caseInfoIterable = caseInfoRepository.findAll(qCaseInfo.currentCollector.id.eq(userModel.getId()).and(qCaseInfo.caseType.eq(CaseType.VISIT_CASE)
                    .and(qCaseInfo.caseDataStatus.eq(CaseDataStatus.IN_POOL))).and(qCaseInfo.publicCaseFlag.eq(PublicCaseFlag.NO_PUBLIC_CASE)));
        }
        List<CaseInfo> caseInfoList = IterableUtils.toList(caseInfoIterable);
        if (!caseInfoList.isEmpty()) {
            List<CompletableFuture<AppHomeResponse>> futures = new ArrayList<>();
            int pageSize = 2000;
            int pageNumber = (int) Math.ceil((double) caseInfoList.size() / (double) pageSize);
            for (int i = 0; i < pageNumber; i++) {
                List<CaseInfo> caseInfos = caseInfoList.stream().skip(i * pageSize).limit(pageSize).collect(Collectors.toList());
                CompletableFuture<AppHomeResponse> task = appHomeTask.getHomeOut(caseInfos, userModel.getId());
                futures.add(task);
            }
            List<AppHomeResponse> responses = new ArrayList<>();
            try {
                for (CompletableFuture<AppHomeResponse> future : futures) {
                    responses.add(future.get());
                }
            } catch (InterruptedException | ExecutionException e) {
                log.error(e.getMessage(), e);
            }
            Double waitCollAmt = response.getWaitCollAmt();
            Double hadPayAmt = response.getHadPayAmt();
            Integer waitOutNum = 0;
            Integer hasOutNum = 0;
            for (AppHomeResponse appHomeResponse : responses) {
                waitCollAmt += appHomeResponse.getWaitCollAmt();
                hadPayAmt += appHomeResponse.getHadPayAmt();
                waitOutNum += appHomeResponse.getWaitOutNum();
                hasOutNum += appHomeResponse.getHasOutNum();
            }
            response.setOutNum(caseInfoList.size());
            response.setWaitCollAmt(waitCollAmt);
            response.setHadPayAmt(hadPayAmt);
            response.setWaitOutNum(waitOutNum);
            response.setHasOutNum(hasOutNum);
        }
        return response;
    }
}
